#include "tcp_server.h"
#include "config.h"
#include "Loggers.h"


namespace sylar
{
	static sylar::ConfigVar<uint64_t>::ptr g_tcp_server_read_timeout =
	sylar::Config::Lookup("tcp_server.read_timeout", (uint64_t)(60 * 1000 * 2), "tcp server read timeout(ms)");

	static Loggers::ptr g_logger = SYLAR_LOG_NAME("system");


	sylar::TcpServer::TcpServer(sylar::IOManager* woker, sylar::IOManager* acceptwoker)
		:m_worker(woker),m_acceptWorker(acceptwoker),m_readTimeout(5000),m_name("sylar/1.0.0"),m_isStop(true)
	{
	}

	TcpServer::~TcpServer()
	{
		for (auto& i : m_socks)
		{
			i->close();
		}
		m_socks.clear();
	}

	bool TcpServer::bind(sylar::Address::ptr addr)
	{
		Socket::ptr sock = Socket::CreateTCP(addr);
		if (!sock->bind(addr))
		{
			SYLAR_LOG_ERROR(g_logger) << " addr=[" << addr->toString() << "]";
			return false;
		}

		if (!sock->listen())
		{
			SYLAR_LOG_ERROR(g_logger)<< " list error addr=[" << addr->toString() << "]";
			return false;
		}

		SYLAR_LOG_INFO(g_logger) << " server bind success: " << *addr;
		m_socks.push_back(sock);
		return true;
	}

	bool TcpServer::bind(const std::vector<Address::ptr>& addrs, std::vector<Address::ptr>& fail)
	{
		bool rt = true;
		for (auto addr : addrs)
		{
			if (!bind(addr))
			{
				fail.push_back(addr);
				rt = false;
			}
		}

		if (!fail.empty())
		{
			m_socks.clear();
			return false;
		}

		return true;
	}


	void TcpServer::startAccept(Socket::ptr sock)
	{
		SYLAR_LOG_INFO(g_logger) << " accept 2";
		while (!m_isStop)
		{
			Socket::ptr client = sock->accept();
			if (client)
			{
				client->setRecvTimeout(m_readTimeout);
				
				m_worker->schedule(std::bind(&TcpServer::handleClient, shared_from_this(), client));
			}
			else
			{
				SYLAR_LOG_ERROR(g_logger) << " accept error=" << errno
					<< " errstr=" << strerror(errno);
			}
		}


	}


	bool TcpServer::start()
	{
		if (!m_isStop)
		{
			return true;
		}
		m_isStop = false;
		for (auto& sock : m_socks)
		{
			m_acceptWorker->schedule(std::bind(&TcpServer::startAccept, shared_from_this(), sock));
		}
		return true;
	}

	bool TcpServer::stop()
	{
		m_isStop = true;
		auto self = shared_from_this();
		m_acceptWorker->schedule([this,self]() {
			for (auto& sock : m_socks)
			{
				sock->cancelAll();
				sock->close();
			}

			m_socks.clear();
			});
		return true;
	}

	void TcpServer::handleClient(Socket::ptr client)
	{
		SYLAR_LOG_INFO(g_logger) << " handleCilent: "<<*client;
	}




}
